home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Expert
/
Windows Expert.iso
/
windownt
/
xvidiff.zip
/
FLEXBUF.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-01
|
7KB
|
401 lines
/* Copyright (c) 1990,1991,1992 Chris and John Downey */
#ifndef lint
static char *sccsid = "@(#)flexbuf.c 2.2 (Chris & John Downey) 8/27/92";
#endif
/***
* program name:
xvi
* function:
PD version of UNIX "vi" editor, with extensions.
* module name:
flexbuf.c
* module function:
Routines for Flexbufs (variable-length FIFO queues).
Some of the access routines are implemented as macros in xvi.h.
* history:
STEVIE - ST Editor for VI Enthusiasts, Version 3.10
Originally by Tim Thompson (twitch!tjt)
Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
Heavily modified by Chris & John Downey
***/
#include "xvi.h"
#define FLEXEXTRA 64
/*
* Append a single character to a Flexbuf. Return FALSE if we've run
* out of space.
*
* Note that the f->fxb_chars array is not necessarily null-terminated.
*/
bool_t
flexaddch(f, ch)
register Flexbuf *f;
int ch;
{
if (flexempty(f))
f->fxb_rcnt = f->fxb_wcnt = 0;
if (f->fxb_wcnt >= f->fxb_max) {
if (f->fxb_max == 0) {
if ((f->fxb_chars = alloc(FLEXEXTRA)) == NULL) {
return FALSE;
} else {
f->fxb_max = FLEXEXTRA;
}
} else {
unsigned newsize = f->fxb_wcnt + FLEXEXTRA;
if ((f->fxb_chars = realloc(f->fxb_chars, newsize)) == NULL) {
f->fxb_wcnt = f->fxb_max = 0;
return FALSE;
} else {
f->fxb_max = newsize;
}
}
}
f->fxb_chars[f->fxb_wcnt++] = ch;
return TRUE;
}
/*
* Return contents of a Flexbuf as a null-terminated string.
*/
char *
flexgetstr(f)
Flexbuf *f;
{
if (!flexempty(f) && flexaddch(f, '\0')) {
--f->fxb_wcnt;
return &f->fxb_chars[f->fxb_rcnt];
} else {
return "";
}
}
/*
* Remove the first character from a Flexbuf and return it.
*/
int
flexpopch(f)
Flexbuf *f;
{
return flexempty(f) ?
0 : (unsigned char) f->fxb_chars[f->fxb_rcnt++];
}
/*
* Free storage belonging to a Flexbuf.
*/
void
flexdelete(f)
Flexbuf *f;
{
if (f->fxb_max > 0) {
(void) free(f->fxb_chars);
f->fxb_wcnt = f->fxb_max = 0;
}
}
/*
* The following routines provide for appending formatted data to a
* Flexbuf using a subset of the format specifiers accepted by
* printf(3). The specifiers we understand are currently
*
* %c %d %ld %lu %s %u
*
* Field width, precision & left justification can also be specified
* as for printf().
*
* The main advantage of this is that we don't have to worry about the
* end of the destination array being overwritten, as we do with
* sprintf(3).
*/
static unsigned width;
static unsigned prec;
static bool_t ljust;
/*
* Append a string to a Flexbuf, truncating the string & adding filler
* characters as specified by the width, prec & ljust variables.
*
* The precision specifier gives the maximum field width.
*/
static bool_t
strformat(f, p)
Flexbuf *f;
register char *p;
{
register int c;
if (width != 0 && !ljust) {
register unsigned len;
len = strlen(p);
if (prec != 0 && prec < len)
len = prec;
while (width > len) {
if (!flexaddch(f, ' '))
return FALSE;
--width;
}
}
while ((c = *p++) != '\0') {
if (!flexaddch(f, c))
return FALSE;
if (width != 0)
--width;
if (prec != 0) {
if (--prec == 0) {
break;
}
}
}
while (width != 0) {
if (!flexaddch(f, ' '))
return FALSE;
--width;
}
return TRUE;
}
/*
* Given a binary long integer, convert it to a decimal number &
* append it to the end of a Flexbuf.
*
* The precision specifier gives the minimum number of decimal digits.
*/
static bool_t
numformat(f, n, uflag)
Flexbuf *f;
long n;
bool_t uflag;
{
register char *s;
register unsigned len;
if (n == 0) {
/*
* Special case.
*/
s = "0";
len = 1;
} else {
static char dstr[sizeof (long) * 3 + 2];
register unsigned long un;
int neg;
* (s = &dstr[sizeof dstr - 1]) = '\0';
if (!uflag && n < 0) {
neg = 1;
un = -n;
} else {
neg = 0;
un = n;
}
while (un > 0 && s > &dstr[1]) {
*--s = (char)((un % 10) + '0');
un /= 10;
}
if (neg)
*--s = '-';
len = &dstr[sizeof dstr - 1] - s;
}
while (width > len && width > prec) {
if (!flexaddch(f, ' '))
return FALSE;
--width;
}
while (prec > len) {
if (!flexaddch(f, '0'))
return FALSE;
--prec;
if (width > 0)
--width;
}
prec = 0;
return strformat(f, s);
}
/*
* Main formatting routine.
*/
bool_t
vformat
#ifdef __STDC__
(Flexbuf *f, register char *format, register va_list argp)
#else
(f, format, argp)
Flexbuf *f;
register char *format;
register va_list argp;
#endif
{
register int c;
while ((c = *format++) != '\0') {
if (c == '%') {
static char cstr[2];
bool_t lnflag;
bool_t zflag;
lnflag = FALSE;
ljust = FALSE;
width = 0;
prec = 0;
zflag = FALSE;
if ((c = *format++) == '-') {
ljust = TRUE;
c = *format++;
}
/*
* Get width specifier.
*/
if (c == '0') {
if (ljust)
/*
* It doesn't make sense to
* have a left-justified
* numeric field with zero
* padding.
*/
return FALSE;
zflag = TRUE;
c = *format++;
}
while (c && is_digit(c)) {
if (width != 0)
width *= 10;
width += (c - '0');
c = *format++;
}
if (c == '.') {
/*
* Get precision specifier.
*/
while ((c = *format++) != '\0' && is_digit(c)) {
if (prec != 0)
prec *= 10;
prec += (c - '0');
}
}
switch (c) {
case '%':
cstr[0] = c;
if (!strformat(f, cstr))
return FALSE;
continue;
case 'c':
cstr[0] = va_arg(argp, int);
if (!strformat(f, cstr))
return FALSE;
continue;
case 'l':
switch (c = *format++) {
case 'd':
case 'u':
lnflag = TRUE;
break;
default:
/*
* Syntax error.
*/
return FALSE;
}
/* fall through ... */
case 'd':
case 'u':
{
long n;
if (lnflag)
{
n = (c == 'u' ?
(long) va_arg(argp, unsigned long) :
va_arg(argp, long));
} else {
n = (c == 'u' ?
(long) va_arg(argp, unsigned int) :
(long) va_arg(argp, int));
}
/*
* For integers, the precision
* specifier gives the minimum number
* of decimal digits.
*/
if (zflag && prec < width) {
prec = width;
width = 0;
}
if (!numformat(f, n, (c == 'u')))
return FALSE;
continue;
}
case 's':
{
char *sp;
if ((sp = va_arg(argp, char *)) == NULL ||
!strformat(f, sp)) {
return FALSE;
}
continue;
}
default:
/*
* Syntax error.
*/
return FALSE;
}
} else if (!flexaddch(f, c)) {
return FALSE;
}
}
return TRUE;
}
/*
* Front end callable with a variable number of arguments.
*/
/*VARARGS2*/
bool_t
lformat
#ifdef __STDC__
(Flexbuf *f, char *format, ...)
#else
(f, format, va_alist)
Flexbuf *f;
char *format;
va_dcl
#endif
{
va_list argp;
bool_t retval;
VA_START(argp, format);
retval = vformat(f, format, argp);
va_end(argp);
return retval;
}